package org.mashart.pink.m.gps;

import java.util.Date;
import javax.microedition.location.*;

/**
 * Implementation of <code>DeviceConnector</code> for built-in GPS
 */
public class InternalGpsConnector implements DeviceConnector, LocationListener{
    public LocationProvider provider;
    public Location location;
    public LocationListener myListener;
    public QualifiedCoordinates qc;
    double lat;
    double lon;
    float alt;
    float acc;
    float spd;
    float hdop;
    float vdop;
    int timeMS;
//    String utc;
    boolean fix;
    String name;

    /**
     * Constructor
     */
    public InternalGpsConnector(){
        qc = null;
        lat = 0.0;
        lon = 0.0;
        alt = (float)0.0;
        acc = (float)0.0;
        spd = (float)0.0;
        hdop = (float)0.0;
        vdop = (float)0.0;
        timeMS = -1;
        fix = false;
    }

    /**
     * Configures the connector. For built-in GPS requires, do nothing.
     * @return 1
     */
    public int configure(){
        return 1;
    }

    /**
     * Discover the built-in GPS device
     */
    public int discover(){
        int res = initialize();
//        terminate();
        return res;
    }

    /**
     * Turns on the built-in GPS device
     * @return 1 if succeeded, otherwise 0
     */
    public int initialize(){
        try{
            // Mobile device with a built-in GPS may also have other positioning
            // mechanisms, e.g., using the WLAN Accss-point or GSM base-station information
            // It is up to user to enable GPS and disable WLAN/base-station positioning
            // here the least restrictive accuracy criteria is set.
            Criteria c = new Criteria();
//            c.setAltitudeRequired(true);
//            c.setSpeedAndCourseRequired(true);
            provider = LocationProvider.getInstance(c);
        } catch (Exception e ) {
            return 0;
        }
        return provider != null ? 1 : 0;
    }

    public int activate(){
        provider.setLocationListener(this, -1, 0, 0);
        return 1;
    }

    public int deactivate(){
        provider.setLocationListener(null, -1, 0, 0); // here
        return 1;
    }


    /**
     * @return a waypoint if the connector is ready, otherwise return null.
     */
    public Waypoint getWaypoint(){
        // if no valid waypoint is received so far
        if(timeMS < 0){
            return null;
        }
        
        Waypoint wp = new Waypoint();
        wp.timeMS = timeMS;
//        wp.utc = utc;
        wp.latitude = lat;
        wp.ns = (lat > 0);
        wp.longitude = lon;
        wp.ew = (lon > 0);
        wp.altitude = alt;
        wp.speed = spd;
        wp.hdop = hdop;
        wp.vdop = vdop;
        wp.fix = fix;
        return wp;
    }

    /**
     * Turns off the built-in GPS device
     * @return 1 if succeeded, otherwise 0
     */
    public int terminate(){
        deactivate();
        try {
            provider.reset();
            return 1;
        } catch (Exception e ) {
            return 0;
        }
    }

    public void locationUpdated(final LocationProvider prov, final Location loc) {
        new Thread() {
            public void run() {
                if (loc != null && loc.isValid()) {
                    qc = loc.getQualifiedCoordinates();
                    lat = qc.getLatitude();
                    lon = qc.getLongitude();
                    alt = qc.getAltitude();
                    hdop = qc.getHorizontalAccuracy();
                    vdop = qc.getVerticalAccuracy();
                    spd = (float) (loc.getSpeed() * 3.6);

                    long t = loc.getTimestamp();
                    int d = (int) (t / (24 * 3600000));
                    // calculate the elapsed milliseconds from 00:00:00, important for calculation
                    timeMS = (int) (t - 24 * 3600000 * d);
//                    // generate a string representing the
//                    Date date = new Date(t);
//                    utc = date.toString();

                    fix = (prov.getState() == LocationProvider.AVAILABLE);

                  }
            }
        }.start();
    }

    public void providerStateChanged(LocationProvider prov, int newState) {
    }
} 